package com.yuanhua.xcxmng.wechat.service.impl;

import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
import java.util.Optional;

import javax.annotation.Resource;

import com.yuanhua.xcxmng.wechat.entity.*;
import com.yuanhua.xcxmng.wechat.mapper.UserDeviceMapper;
import com.yuanhua.xcxmng.wechat.service.UserDeviceService;
import org.apache.commons.lang3.StringUtils;
import org.joda.time.DateTime;
import org.joda.time.Years;
import org.joda.time.format.DateTimeFormat;
import org.springframework.stereotype.Service;

import com.google.common.collect.Lists;
import com.yuanhua.xcxmng.wechat.mapper.UserIndicatorMapper;
import com.yuanhua.xcxmng.wechat.service.IndicatorService;

import cn.hutool.core.date.DateUtil;
import org.springframework.util.CollectionUtils;

/**
 * The type Indicator service.
 *
 * @author hzy24985
 * @version $Id : IndicatorServiceImpl, v 0.1 2018/8/5 下午11:20 hzy24985 Exp $
 */
@Service
public class IndicatorServiceImpl implements IndicatorService {
    @Resource
    private UserIndicatorMapper userIndicatorMapper;
    @Resource
    private UserDeviceService userDeviceService;

    @Override
    public int save(UserIndicator indicator, User user) {
        indicator.setCreateTime(new Date());
        indicator.setUnit(user.getUnit());

        DateTime birthday = DateTime.parse(user.getAge(), DateTimeFormat.forPattern("yyyy-MM-dd"));
        indicator.setAge(Years.yearsBetween(birthday, DateTime.now()).getYears());
        indicator.setHeight(user.getHeight());
        indicator.setOpenId(user.getOpenId());
        indicator.setUnionId(user.getUnionId());
        int count = userIndicatorMapper.insert(indicator);
        userDeviceService.saveDeviceLink(indicator.getDeviceId(), user);
        return count;
    }

    @Override
    public List<UserIndicator> getLatestRecord(String openId, Date startOfMonth, Date endOfMonth, int n) {
        return userIndicatorMapper.getLatestRecord(new IndicatorLatestRecordQuery(openId, startOfMonth, endOfMonth, n));
    }

    @Override
    public List<UserIndicator> getIndicatorReport(String openId, Date startOfMonth, Date endOfMonth) {
        return userIndicatorMapper.getIndicatorReport(new IndicatorLatestRecordQuery(openId, startOfMonth, endOfMonth, 31));
    }

    @Override
    public List<HistoryTable> getHistoryTableData(String openId, int index, List<Date> latest5Month) {
        List<HistoryTable> result = Lists.newArrayList();

        Date now = latest5Month.get(index);

        cn.hutool.core.date.DateTime startOfWeek = DateUtil.beginOfWeek(now);
        cn.hutool.core.date.DateTime endOfWeek = DateUtil.endOfWeek(now);
        cn.hutool.core.date.DateTime startOfMonth = DateUtil.beginOfMonth(now);
        cn.hutool.core.date.DateTime endOfMonth = DateUtil.endOfMonth(now);

        List<UserIndicator> weeksData = getIndicatorReport(openId, startOfWeek, endOfWeek);
        List<UserIndicator> monthData = getIndicatorReport(openId, startOfMonth, endOfMonth);

        List<String> weeks = getDate(startOfWeek, endOfWeek, true);
        List<String> months = getDate(startOfMonth, endOfMonth, false);

        result.add(generateData(weeksData, weeks));
        result.add(generateData(monthData, months));
        return result;
    }

    /**
     * 生成图表数据.
     * 数据库中存的是测量的原始值，在图表上不方便在做数据处理，
     * 所以这里直接做了数据处理（除以10，保留一位小数），展示到曲线图上。
     * 没有测量数据的日志，默认给0.
     * @param data 测量数据
     * @param datetime 日期
     * @return 生成图表数据
     */
    private HistoryTable generateData(List<UserIndicator> data, List<String> datetime) {
        HistoryTable dataTable = new HistoryTable(datetime);
        for (String date : datetime) {
            boolean isFind = false;
            for (UserIndicator indicator : data) {
                if (DateUtil.formatDate(indicator.getCreateTime()).equals(date)) {
                    isFind = true;
                    dataTable.getBmi().add(getValue(indicator.getBmi()));
                    dataTable.getWeight().add(getValue(indicator.getWeight()));
                    dataTable.getTzRate().add(getValue(indicator.getTzRate()));
                    break;
                }
            }
            if (!isFind) {
                dataTable.getBmi().add(0D);
                dataTable.getWeight().add(0D);
                dataTable.getTzRate().add(0D);
            }
        }
        return dataTable;
    }

    /**
     * 数值除以10后的数据
     * @param value 值
     * @return 数值除以10后的数据
     */
    private double getValue(int value) {
        return new BigDecimal(value)
                .setScale(1, BigDecimal.ROUND_CEILING)
                .divide(BigDecimal.valueOf(10), BigDecimal.ROUND_CEILING)
                .doubleValue();
    }

    /**
     * 生成日期列表
     * @param startDate 开始时间
     * @param endDate 结束时间
     * @param showNextDay 是否展示今天以后的数据。
     * @return 日期列表。
     */
    private List<String> getDate(cn.hutool.core.date.DateTime startDate, cn.hutool.core.date.DateTime endDate, boolean showNextDay) {
        List<String> date = Lists.newArrayList();
        cn.hutool.core.date.DateTime next = DateUtil.offsetDay(startDate, -1);
        while (true) {
            next = DateUtil.offsetDay(next, 1);
            if (next.isBeforeOrEquals(endDate)) {
                if (!showNextDay && !next.isBeforeOrEquals(new Date())) {
                    break;
                }
                date.add(next.toDateStr());
            } else {
                break;
            }
        }
        return date;
    }

}
